package com.loveprogrammer.eternity.model.product;

import com.loveprogrammer.eternity.enums.*;
import com.loveprogrammer.eternity.model.Character;
import com.loveprogrammer.eternity.model.Hero;
import com.loveprogrammer.eternity.model.effect.AbstractEffect;
import com.loveprogrammer.eternity.skill.State;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @version 1.0.0
 * @description: 装备
 * @author: eric
 * @date: 2022-08-03 10:43
 **/
public class Equipment extends Goods {

    private int suitId;                   // 如果是套装，套装的id
    private int strength;                  // 力量 影响物理输出 物理技能输出
    private int armature;                 // 护甲值 影响物理防御和法术防御
    private int constitution;               // 体质 影响生命值 一点体质增加10点生命值
    private int magic;                       // 魔力 影响法术输出 法术技能输出
    private int technique;                   // 技巧 影响闪避率、暴击率
    private int speed;                         // 攻击速度

    private int hp;                            // 生命值
    private int evasion;

    private int fortune;

    private boolean used = false;   // 是否被使用

    // 如果constant == true，不能增加前缀，属于固定属性装备
    private boolean constant = false;

    // 如果specifyDrop == true，只有特定的副本或者特定的野怪才能掉落
    private boolean specifyDrop = false;

    // 武器位置
    public EquipmentEnum equipmentPosition;

    // 武器类型
    private WeaponTypeEnum weaponTypeEnum;

    private List<String> affixList;

    private List<State> states;

    private int difference;

    public Equipment(String name, String type, String desc, QualityEnum quality, int strength,
                     int armature, int constitution, int magic, int technique, int speed, int hp,
                     int evasion, int fortune, boolean used, boolean constant, boolean specifyDrop,
                     EquipmentEnum equipmentPosition, List<String> affixList,
                     WeaponTypeEnum weaponTypeEnum,int suitId,int level,int poisonResistance,
                     int flameResistance,int thunderResistance,int iceResistance,List<Goods.GoodsEffectTemplate> effects,int goodsId) {
        this(name, type, desc, quality, strength, armature, constitution, magic, technique, speed,
                hp, evasion, fortune, used, equipmentPosition, weaponTypeEnum, affixList, level,
                poisonResistance,flameResistance,thunderResistance,iceResistance,effects,goodsId);
        this.constant = constant;
        this.specifyDrop = specifyDrop;
        this.suitId = suitId;
    }

    public Equipment(String name, String type, String desc, QualityEnum quality, int strength,
                     int armature, int constitution, int magic, int technique, int speed, int hp,
                     int evasion, int fortune, boolean used, EquipmentEnum equipmentPosition,
                     WeaponTypeEnum weaponTypeEnum, List<String> affixList, int level,
                     int poisonResistance,int flameResistance,int thunderResistance,int iceResistance,
                     List<Goods.GoodsEffectTemplate> effects,int goodsId) {
        super(name, type, desc, quality, level,poisonResistance,flameResistance,
                thunderResistance,iceResistance,effects,goodsId);
        this.strength = strength;
        this.armature = armature;
        this.constitution = constitution;
        this.magic = magic;
        this.technique = technique;
        this.speed = speed;
        this.hp = hp;
        this.evasion = evasion;
        this.fortune = fortune;
        this.equipmentPosition = equipmentPosition;
        this.weaponTypeEnum = weaponTypeEnum;
        this.used = used;
        if(affixList == null){
            affixList = new ArrayList<>();
        }
        this.affixList = affixList;
    }

    public Equipment(String name, String type, String desc, EquipmentEnum equipmentEnum,
                     QualityEnum quality,int goodsId) {
        super(name, type, desc, quality,goodsId);
        this.equipmentPosition = equipmentEnum;
        this.affixList = new ArrayList<>();
    }

    // 物品打印信息的重写
    @Override
    public String toString() {
        return "*物品信息* " +
                "名称：" + getName() + " " + "级别：" + getLevel() + " " +
                "品质：" + this.quality.getColor() + this.quality.getDesc() + ConsoleColors.RESET + " " +
                (strength > 0 ? ("力量：" + strength + " ") : "") +
                (armature > 0 ? ("护甲：" + armature + " ") : "") +
                (constitution > 0 ? ("体力：" + constitution + " ") : "") +
                (magic > 0 ? ("魔力：" + magic + " ") : "") +
                (technique > 0 ? ("技巧：" + technique + " ") : "") +
                (speed > 0 ? ("速度：" + speed + " ") : "") +
                (getPoisonResistance() > 0 ? ("毒抗：" + getPoisonResistance() + " ") : "") +
                (getFlameResistance() > 0 ? ("火抗：" + getFlameResistance() + " ") : "") +
                (getThunderResistance() > 0 ? ("雷抗：" + getThunderResistance() + " ") : "") +
                (getIceResistance() > 0 ? ("冰抗：" + getIceResistance() + " ") : "") +
                "；";
    }

    // 物品打印信息的重写
    public String prettyPrint() {
        return string + "****物品信息****\n" +
                string + "名称：" + getName() + "\n" +
                string + "品质：" + this.quality.getColor() + this.quality.getDesc() + ConsoleColors.RESET + "\n" +
                string + "位置：" + Optional.ofNullable(this.getEquipmentPosition()).orElse(EquipmentEnum.UNKOWN).getDesc() + "\n" +
                string + "说明：" + getDesc() + "\n" +
                (strength > 0 ? (string + "力量：" + strength + "\n") : "") +
                (armature > 0 ? (string + "护甲：" + armature + "\n") : "") +
                (constitution > 0 ? (string + "体力：" + constitution + "\n") : "") +
                (magic > 0 ? (string + "魔力：" + magic + "\n") : "") +
                (technique > 0 ? (string + "技巧：" + technique + "\n") : "") +
                (speed > 0 ? (string + "速度：" + speed + "\n") : "") +
                (getPoisonResistance() > 0 ? (string + "毒抗：" + getPoisonResistance() + "\n") : "") +
                (getFlameResistance() > 0 ? (string + "火抗：" + getFlameResistance() + "\n") : "") +
                (getThunderResistance() > 0 ? (string + "雷抗：" + getThunderResistance() + "\n") : "") +
                (getIceResistance() > 0 ? (string + "冰抗：" + getIceResistance() + "\n") : "") +
                string + "" + "***************";
    }

    @Override
    public Coin sale() {
        Coin coin = new Coin();
        int gold = (int) (score() + getLevel() * quality.getRatio());
        coin.setGoldCoin(gold);
        return coin;
    }

    @Override
    public Coin price() {
        Coin sale = sale();
        Coin price = new Coin();
        int factor = 30;
        int affNum = affixList.size();
        switch (affNum) {
            case 0:
                factor = factor;
                break;
            case 1:
                factor = factor * 2;
                break;
            case 2:
                factor = factor * 4;
                break;
            case 3:
                factor = factor * 8;
                break;
            case 4:
                factor = factor * 16;
                break;
        }
        price.setDiamonds(sale.getDiamonds() * factor);
        price.setGoldCoin(sale.getGoldCoin() * factor);
        return price;
    }

    public int score(Hero hero) {
        int id = hero.getTemplate().getId();
        HeroPropertiesEnum propertiesEnum = HeroPropertiesEnum.getById(id);
        return (int) (strength * propertiesEnum.getStrengthRatio()
                        + armature * propertiesEnum.getArmatureRatio()
                        + constitution * propertiesEnum.getConstitutionRatio()
                        + magic * propertiesEnum.getMagicRatio()
                        + technique * propertiesEnum.getTechniqueRatio()
                        + speed * propertiesEnum.getSpeedRatio());
    }

    public int score() {
        return strength + armature * 2 + constitution + magic + technique + speed;
    }

    public int getStrength() {
        return strength;
    }

    public void setStrength(int strength) {
        this.strength = strength;
    }

    public int getArmature() {
        return armature;
    }

    public void setArmature(int armature) {
        this.armature = armature;
    }

    public int getConstitution() {
        return constitution;
    }

    public void setConstitution(int constitution) {
        this.constitution = constitution;
    }

    public int getMagic() {
        return magic;
    }

    public void setMagic(int magic) {
        this.magic = magic;
    }

    public int getTechnique() {
        return technique;
    }

    public void setTechnique(int technique) {
        this.technique = technique;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getHp() {
        return hp;
    }

    public void setHp(int hp) {
        this.hp = hp;
    }

    public int getEvasion() {
        return evasion;
    }

    public void setEvasion(int evasion) {
        this.evasion = evasion;
    }

    public int getFortune() {
        return fortune;
    }

    public void setFortune(int fortune) {
        this.fortune = fortune;
    }

    public WeaponTypeEnum getWeaponTypeEnum() {
        return weaponTypeEnum;
    }

    public void setWeaponTypeEnum(WeaponTypeEnum weaponTypeEnum) {
        this.weaponTypeEnum = weaponTypeEnum;
    }

    public EquipmentEnum getEquipmentPosition() {
        return equipmentPosition;
    }

    public void setEquipmentPosition(EquipmentEnum equipmentPosition) {
        this.equipmentPosition = equipmentPosition;
    }

    public boolean isUsed() {
        return used;
    }

    public void setUsed(boolean used) {
        this.used = used;
    }

    public boolean isConstant() {
        return constant;
    }

    public void setConstant(boolean constant) {
        this.constant = constant;
    }

    public boolean isSpecifyDrop() {
        return specifyDrop;
    }

    public void setSpecifyDrop(boolean specifyDrop) {
        this.specifyDrop = specifyDrop;
    }

    public List<String> getAffixList() {
        return affixList;
    }

    public void setAffixList(List<String> affixList) {
        this.affixList = affixList;
    }

    public int getSuitId() {
        return suitId;
    }

    public void setSuitId(int suitId) {
        this.suitId = suitId;
    }

    public List<State> getStates() {
        return states;
    }

    public void setStates(List<State> states) {
        this.states = states;
    }

    // 检查并更新套装效果
    public void checkSuitEffect(Character character, Equipment equipment){
        // 先看当前的套装情况
    }

    public int getDifference() {
        return difference;
    }

    public void setDifference(int difference) {
        this.difference = difference;
    }

    public String showDifference(Equipment position, Hero hero) {
        HeroPropertiesEnum propertiesEnum = HeroPropertiesEnum.getById(hero.getTemplate().getId());
        StringBuilder builder = new StringBuilder();

        int strengthDif = strength - (position == null ? 0 : position.getStrength());
        int magicDif = magic - (position == null ? 0 : position.getMagic());
        int armatureDif = armature - (position == null ? 0 : position.getArmature());
        int speedDif = speed - (position == null ? 0 : position.getSpeed());
        int techniqueDif = technique  - (position == null ? 0 : position.getTechnique());
        int constitutionDif = constitution - (position == null ? 0 : position.getConstitution());

        builder.append("*物品信息* " + "名称：")
                .append(getName()).append(" ")
                .append("级别：").append(getLevel()).append(" ")
                .append("品质：").append(this.quality.getColor()).append(this.quality.getDesc()).append(ConsoleColors.RESET).append(" ");

        if(strengthDif > 0) {
            builder.append(" 力：").append(strength).append("(").append(ConsoleColors.RED_BOLD).append(strengthDif)
                    .append(ConsoleColors.RESET).append(")");
        }else{
            builder.append(" 力：").append(strength).append("(").append(ConsoleColors.GREEN_BOLD).append(strengthDif)
                    .append(ConsoleColors.RESET).append(")");
        }

        if(speedDif > 0) {
            builder.append(" 速：").append(speed).append("(").append(ConsoleColors.RED_BOLD).append(speedDif)
                    .append(ConsoleColors.RESET).append(")");
        }else{
            builder.append(" 速：").append(speed).append("(").append(ConsoleColors.GREEN_BOLD).append(speedDif)
                    .append(ConsoleColors.RESET).append(")");
        }

        if(magicDif > 0) {
            builder.append(" 法：").append(magic).append("(").append(ConsoleColors.RED_BOLD).append(magicDif)
                    .append(ConsoleColors.RESET).append(")");
        }else{
            builder.append(" 法：").append(magic).append("(").append(ConsoleColors.GREEN_BOLD).append(magicDif)
                    .append(ConsoleColors.RESET).append(")");
        }

        if(constitutionDif > 0) {
            builder.append(" 体：").append(constitution).append("(").append(ConsoleColors.RED_BOLD)
                    .append(constitutionDif).append(ConsoleColors.RESET).append(")");
        }else{
            builder.append(" 体：").append(constitution).append("(").append(ConsoleColors.GREEN_BOLD)
                    .append(constitutionDif).append(ConsoleColors.RESET).append(")");
        }

        if(armatureDif > 0) {
            builder.append(" 甲：").append(armature).append("(").append(ConsoleColors.RED_BOLD)
                    .append(armatureDif).append(ConsoleColors.RESET).append(")");
        }else{
            builder.append(" 甲：").append(armature).append("(").append(ConsoleColors.GREEN_BOLD)
                    .append(armatureDif).append(ConsoleColors.RESET).append(")");
        }

        if(techniqueDif > 0) {
            builder.append(" 技：").append(technique).append("(").append(ConsoleColors.RED_BOLD).append(techniqueDif)
                    .append(ConsoleColors.RESET).append(")");
        }else{
            builder.append(" 技：").append(technique).append("(").append(ConsoleColors.GREEN_BOLD).append(techniqueDif)
                    .append(ConsoleColors.RESET).append(")");
        }

        builder.append("；");

        return builder.toString();
    }
}
